package io.youngledo.usb.task;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
 * 任务管理器 - 使用Java 21优化版本
 * 提供完整的后台任务管理功能
 */
@Slf4j
public class TaskManager {


    // 线程池管理
    private final ExecutorService taskExecutor;
    private final ScheduledExecutorService scheduledExecutor;

    // 任务存储
    private final Map<String, StorageTask> activeTasks = new ConcurrentHashMap<>();
    private final Map<String, StorageTask> completedTasks = new ConcurrentHashMap<>();
    /**
     * -- GETTER --
     *  获取所有任务（用于UI绑定）
     */
    @Getter
    private final ObservableList<StorageTask> allTasks = FXCollections.synchronizedObservableList(
            FXCollections.observableArrayList()
    );

    // 任务计数器
    private final AtomicInteger taskCounter = new AtomicInteger(0);

    // 配置
    private final int maxConcurrentTasks;
    private final int maxHistoryTasks;

    // 回调函数列表
    private final List<Consumer<StorageTask>> onTaskAddedListeners = new ArrayList<>();
    private final List<Consumer<StorageTask>> onTaskCompletedListeners = new ArrayList<>();
    private final List<Consumer<StorageTask>> onTaskFailedListeners = new ArrayList<>();

    private TaskManager() {
        this.maxConcurrentTasks = Runtime.getRuntime().availableProcessors() * 2;
        this.maxHistoryTasks = 100;

        // 创建线程池
        this.taskExecutor = Executors.newFixedThreadPool(
                maxConcurrentTasks,
                r -> {
                    Thread t = new Thread(r, "StorageTask-" + taskCounter.incrementAndGet());
                    t.setDaemon(true);
                    return t;
                }
        );

        this.scheduledExecutor = Executors.newScheduledThreadPool(2);

        // 启动清理任务
        startCleanupTask();
    }

    private static final class InstanceHolder {
        private static final TaskManager instance = new TaskManager();
    }

    public static TaskManager getInstance() {
        return InstanceHolder.instance;
    }

    /**
     * 创建带进度跟踪的上传任务
     */
    public String submitUploadTask(String description, String connectionId, String bucketName,
                                   List<String> files, Callable<Void> operation, long totalBytes) {

        String taskId = generateTaskId();

        ProgressTracker progressTracker = new ProgressTracker(taskId, TaskType.UPLOAD, description);
        progressTracker.setTotalBytes(totalBytes); // 在创建时就设置totalBytes

        StorageTask task = new StorageTask(
                taskId, TaskType.UPLOAD, description,
                connectionId, bucketName, files,
                operation, progressTracker
        );

        // 设置任务回调
        setupTaskCallbacks(task);

        // 添加到活动任务列表
        activeTasks.put(taskId, task);
        Platform.runLater(() -> allTasks.add(task));

        // 提交到线程池执行
        try {
            // 添加失败处理
            task.setOnFailed(e -> {
                Throwable exception = task.getException();
                if (exception != null) {
                    log.error("StorageTask failed [{}]: {}", taskId, description, exception);
                } else {
                    log.error("StorageTask failed [{}]: {} - No exception details", taskId, description);
                }
            });

            taskExecutor.submit(task);
            log.debug("Task {} submitted to executor successfully", taskId);
        } catch (Exception e) {
            log.error("Failed to submit task {}: {}", taskId, e.getMessage(), e);
            handleTaskError(task, e);
        }

        log.info("Task submitted: {} [{}] - {}", taskId, TaskType.UPLOAD.getDisplayName(), description);

        // 触发任务添加回调
        for (Consumer<StorageTask> listener : onTaskAddedListeners) {
            listener.accept(task);
        }

        return taskId;
    }

    /**
     * 创建带进度跟踪的下载任务
     */
    public String submitDownloadTask(String description, String connectionId, String bucketName,
                                     List<String> files, Callable<Void> operation, long totalBytes) {

        // 检查许可证限制：社区版只能有1个活动下载任务
        if (!io.youngledo.usb.license.FeatureGate.isEnabled(io.youngledo.usb.license.Feature.TASK_MANAGEMENT)) {
            long activeDownloadCount = activeTasks.values().stream()
                    .filter(task -> task.getTaskType() == TaskType.DOWNLOAD)
                    .filter(task -> task.getState() == javafx.concurrent.Worker.State.RUNNING ||
                                   task.getState() == javafx.concurrent.Worker.State.SCHEDULED)
                    .count();

            if (activeDownloadCount >= 1) {
                // 社区版已有1个下载任务在运行，拒绝新任务
                return null;
            }
        }

        String taskId = generateTaskId();

        ProgressTracker progressTracker = new ProgressTracker(taskId, TaskType.DOWNLOAD, description);
        progressTracker.setTotalBytes(totalBytes); // 在创建时就设置totalBytes

        StorageTask task = new StorageTask(
                taskId, TaskType.DOWNLOAD, description,
                connectionId, bucketName, files,
                operation, progressTracker
        );

        // 设置任务回调
        setupTaskCallbacks(task);

        // 添加到活动任务列表
        activeTasks.put(taskId, task);
        Platform.runLater(() -> allTasks.add(task));

        // 提交到线程池执行
        try {
            // 添加失败处理
            task.setOnFailed(e -> {
                Throwable exception = task.getException();
                if (exception != null) {
                    log.error("StorageTask failed [{}]: {}", taskId, description, exception);
                } else {
                    log.error("StorageTask failed [{}]: {} - No exception details", taskId, description);
                }
            });

            taskExecutor.submit(task);
            log.debug("Task {} submitted to executor successfully", taskId);
        } catch (Exception e) {
            log.error("Failed to submit task {}: {}", taskId, e.getMessage(), e);
            handleTaskError(task, e);
        }

        log.info("Task submitted: {} [{}] - {}", taskId, TaskType.DOWNLOAD.getDisplayName(), description);

        // 触发任务添加回调
        for (Consumer<StorageTask> listener : onTaskAddedListeners) {
            listener.accept(task);
        }

        return taskId;
    }

    /**
     * 获取任务
     */
    public StorageTask getTask(String taskId) {
        if (taskId == null) {
            log.warn("Cannot get task: taskId is null");
            return null;
        }
        StorageTask task = activeTasks.get(taskId);
        return task != null ? task : completedTasks.get(taskId);
    }

    /**
     * 获取当前正在执行的任务（线程本地）
     */
    private final ThreadLocal<StorageTask> currentTask = new ThreadLocal<>();

    public StorageTask getCurrentTask() {
        return currentTask.get();
    }

    public void setCurrentTask(StorageTask task) {
        currentTask.set(task);
    }

    public void clearCurrentTask() {
        currentTask.remove();
    }

    /**
     * 取消任务
     */
    public boolean cancelTask(String taskId) {
        if (taskId == null) {
            log.warn("Cannot cancel task: taskId is null");
            return false;
        }
        StorageTask task = activeTasks.get(taskId);
        if (task != null && !task.isDone()) {
            task.cancel();
            log.info("Task cancelled: {}", taskId);
            return true;
        }
        return false;
    }

    /**
     * 暂停任务
     */
    public boolean pauseTask(String taskId) {
        if (taskId == null) {
            log.warn("Cannot pause task: taskId is null");
            return false;
        }
        StorageTask task = activeTasks.get(taskId);
        if (task != null && task.isRunning()) {
            task.pause();
            log.info("Task paused: {}", taskId);
            return true;
        }
        return false;
    }

    /**
     * 恢复任务
     */
    public boolean resumeTask(String taskId) {
        if (taskId == null) {
            log.warn("Cannot resume task: taskId is null");
            return false;
        }
        StorageTask task = activeTasks.get(taskId);
        if (task != null && task.getTaskStatus() == TaskStatus.PAUSED) {
            task.resume();
            log.info("Task resumed: {}", taskId);
            return true;
        }
        return false;
    }

    /**
     * 获取所有活动任务
     */
    public List<StorageTask> getActiveTasks() {
        return new ArrayList<>(activeTasks.values());
    }

    /**
     * 获取任务统计信息
     */
    public TaskStatistics getStatistics() {
        // 计算活动任务数
        int active = activeTasks.size();

        int running = (int) activeTasks.values().stream()
                .mapToLong(task -> task.getTaskStatus() == TaskStatus.RUNNING ? 1 : 0)
                .sum();

        int completed = completedTasks.size();

        return new TaskStatistics(active, running, completed, maxConcurrentTasks);
    }

    /**
     * 清理已完成的任务
     */
    public void cleanupCompletedTasks() {
        // 保留最近的历史任务
        if (completedTasks.size() > maxHistoryTasks) {
            List<StorageTask> sortedTasks = completedTasks.values().stream()
                    .sorted((a, b) -> b.getCreatedTime().compareTo(a.getCreatedTime()))
                    .toList();

            // 移除最老的任务
            for (int i = maxHistoryTasks; i < sortedTasks.size(); i++) {
                StorageTask taskToRemove = sortedTasks.get(i);
                completedTasks.remove(taskToRemove.getTaskId());
                Platform.runLater(() -> allTasks.remove(taskToRemove));
            }

            log.info("Cleaned up {} old completed tasks", sortedTasks.size() - maxHistoryTasks);
        }
    }

    /**
     * 提交通用的JavaFX Task到线程池
     */
    public <T> void submitTask(javafx.concurrent.Task<T> task) {
        if (task == null) {
            log.warn("Cannot submit null task");
            return;
        }

        // 添加失败处理
        task.setOnFailed(e -> {
            Throwable exception = task.getException();
            if (exception != null) {
                log.error("JavaFX Task failed: {}", task.getTitle(), exception);
            } else {
                log.error("JavaFX Task failed: {} - No exception details", task.getTitle());
            }
        });

        taskExecutor.submit(task);
    }

    /**
     * 关闭任务管理器
     */
    public void shutdown() {
        // 取消所有活动任务
        activeTasks.values().forEach(task -> {
            if (!task.isDone()) {
                task.cancel();
            }
        });

        // 关闭线程池
        taskExecutor.shutdown();
        scheduledExecutor.shutdown();

        try {
            if (!taskExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
                taskExecutor.shutdownNow();
            }
            if (!scheduledExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduledExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            taskExecutor.shutdownNow();
            scheduledExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    // 私有方法

    private String generateTaskId() {
        return "task-" + System.currentTimeMillis() + "-" + taskCounter.incrementAndGet();
    }

    private void setupTaskCallbacks(StorageTask task) {
        task.setOnTaskCompleted(this::handleTaskCompleted);
        task.setOnTaskFailed(this::handleTaskFailed);
        task.setOnTaskCancelled(this::handleTaskCancelled);
    }

    private void handleTaskCompleted(StorageTask task) {
        moveToCompleted(task);
        log.info("Task completed: {}", task.getTaskId());

        for (Consumer<StorageTask> listener : onTaskCompletedListeners) {
            listener.accept(task);
        }
    }

    private void handleTaskFailed(StorageTask task) {
        moveToCompleted(task);

        // 更详细的错误日志
        Throwable exception = task.getException();
        if (exception != null) {
            log.error("Task failed [{}]: {}", task.getTaskId(), task.getDescription(), exception);
        } else {
            log.error("Task failed [{}]: {} - No exception details available",
                task.getTaskId(), task.getDescription());
        }

        for (Consumer<StorageTask> listener : onTaskFailedListeners) {
            listener.accept(task);
        }
    }

    private void handleTaskCancelled(StorageTask task) {
        moveToCompleted(task);
        log.info("Task cancelled: {}", task.getTaskId());
    }

    private void handleTaskError(StorageTask task, Exception error) {
        task.getProgressTracker().fail(error.getMessage());
        moveToCompleted(task);
    }

    private void moveToCompleted(StorageTask task) {
        if (task == null) {
            log.warn("Cannot move null task to completed");
            return;
        }
        String taskId = task.getTaskId();
        if (taskId == null) {
            log.warn("Cannot move task to completed: taskId is null");
            return;
        }
        activeTasks.remove(taskId);
        completedTasks.put(taskId, task);
    }

    private void startCleanupTask() {
        scheduledExecutor.scheduleAtFixedRate(
                this::cleanupCompletedTasks,
                1, 1, TimeUnit.HOURS
        );
    }

    // Callback listeners
    public void addOnTaskAddedListener(Consumer<StorageTask> listener) {
        onTaskAddedListeners.add(listener);
    }

    public void addOnTaskCompletedListener(Consumer<StorageTask> listener) {
        onTaskCompletedListeners.add(listener);
    }

    public void addOnTaskFailedListener(Consumer<StorageTask> listener) {
        onTaskFailedListeners.add(listener);
    }

    public void removeOnTaskAddedListener(Consumer<StorageTask> listener) {
        onTaskAddedListeners.remove(listener);
    }

    public void removeOnTaskCompletedListener(Consumer<StorageTask> listener) {
        onTaskCompletedListeners.remove(listener);
    }

    public void removeOnTaskFailedListener(Consumer<StorageTask> listener) {
        onTaskFailedListeners.remove(listener);
    }

    // 保持向后兼容的方法
    public void setOnTaskAdded(Consumer<StorageTask> callback) {
        onTaskAddedListeners.clear();
        if (callback != null) {
            onTaskAddedListeners.add(callback);
        }
    }

    public void setOnTaskCompleted(Consumer<StorageTask> callback) {
        onTaskCompletedListeners.clear();
        if (callback != null) {
            onTaskCompletedListeners.add(callback);
        }
    }

    public void setOnTaskFailed(Consumer<StorageTask> callback) {
        onTaskFailedListeners.clear();
        if (callback != null) {
            onTaskFailedListeners.add(callback);
        }
    }

    /**
     * 任务统计信息记录
     */
    public record TaskStatistics(
            int activeTasks,
            int runningTasks,
            int completedTasks,
            int maxConcurrentTasks
    ) {
        public double getLoadPercentage() {
            return maxConcurrentTasks > 0 ? (double) runningTasks / maxConcurrentTasks * 100 : 0;
        }

        public String getFormattedLoad() {
            return String.format("%.1f%%", getLoadPercentage());
        }
    }
}